package com.chenfan.filestore.controller;

import com.chenfan.ccp.common.exception.ApiException;
import com.chenfan.ccp.common.result.R;
import com.chenfan.filestore.exception.FileStoreCode;
import com.chenfan.filestore.model.MinioMetaInfo;
import com.chenfan.filestore.repository.MinioTemplate;
import com.chenfan.filestore.service.FileService;
import com.chenfan.filestore.utils.FileUtil;
import com.chenfan.filestore.vo.FileDataResult;
import com.chenfan.filestore.vo.FileResult;
import io.minio.messages.Bucket;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

/**
 * @author K
 * @date 2021-05-27
 */
@RestController
@RequestMapping("/feign/file")
public class FileFeignController {

    public static final int DOWNLOAD_THRESHOLD = 50;

    @Autowired
    private MinioTemplate minioTemplate;
    @Autowired
    private FileService fileService;

    @ApiOperation("文件上传拿到文件名称和id(feign)")
    @PostMapping("/upload")
    public R<FileResult> uploadFile(@RequestPart(value = "file") MultipartFile file) throws IOException {
        try {
            return R.data(fileService.uploadFile(file));
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail(e.getMessage());
        }
    }


    @ApiOperation("根据文件ID拿到二进制流数据(后端用)")
    @PostMapping("")
    public R<List<FileDataResult>> getFileData(@RequestBody List<String> fileIdList) {
        if (CollectionUtils.isEmpty(fileIdList)) {
            throw new ApiException(FileStoreCode.FILEID_CANNOT_BE_NULL);
        }

        if (fileIdList.size() > DOWNLOAD_THRESHOLD) {
            throw new ApiException(FileStoreCode.FILE_QUANTITY_OVER_THRESHOLD);
        }
        List<CompletableFuture<FileDataResult>> fileCompleteList = new ArrayList<>();
        for(String fileId: fileIdList) {
            CompletableFuture<FileDataResult> future = CompletableFuture.supplyAsync(() -> {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                InputStream inputStream = minioTemplate.getObject(MinioTemplate.DEFAULT_BUCKETNAME, fileId);
                try {
                    IOUtils.copy(inputStream, bos);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                byte[] bytes = bos.toByteArray();
                return FileDataResult.builder().id(fileId).data(bytes).build();
            });
            fileCompleteList.add(future);
        }

        List<FileDataResult> fileDataList = fileCompleteList.stream().map(e -> {
            try {
                return e.get();
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            } catch (ExecutionException exe) {
                exe.printStackTrace();
            }
            return null;
        }).filter(Objects::nonNull).collect(Collectors.toList());
        return R.data(fileDataList);
    }

    @ApiOperation("上传文件拿到文件名和id")
    @Deprecated
    @PostMapping("/upload-file")
        public R<FileResult> uploadWithBucket(@RequestPart(value = "file") MultipartFile file, String bucketName,  String orderNo) {
        // 检查Bucket是否存在.
        Optional<Bucket> bucketOptional = minioTemplate.getBucket(bucketName);
        if (!bucketOptional.isPresent()) {
            throw new ApiException(FileStoreCode.BUCKET_ERROR);
        }
        String filename = file.getOriginalFilename();
        String[] split = filename.split("\\.");
        String suffix = split[split.length - 1];
        // 文件类型
        String contentType = file.getContentType();

        try {
            String uploadFileName = String.format("%s_%s.%s", orderNo, split[0], suffix);
            Map<String, String> headerMap = new HashMap<>(2);
            headerMap.put("Content-Type", contentType);
            headerMap.put(MinioMetaInfo.ORIGNAL_FILE_NAME, java.util.Base64.getEncoder().encodeToString(filename.getBytes()));
            minioTemplate.putObject(bucketName, uploadFileName, file.getInputStream(), file.getSize(), headerMap);
            return R.data(FileResult.builder().fileName(filename).id(uploadFileName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return R.fail(e.getMessage());
        }
    }
}
